package org.generics.fruits;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Super class in fruits hierarchy.
 */
class Fruit {

    protected int someId;

    Fruit(int someId) {
        this.someId = someId;
    }

    /**
     * Copies all the elements from one collection to another.
     * Is designed for use with Fruits.
     * @param collection copy from
     * @param out copy to
     * @param <T> some type from fruits hierarchy
     */
    public static <T extends Fruit> void copyAll(Collection<T> collection, Collection<? super T> out) {

        for (T obj : collection) {
            out.add(obj);
        }
    }

    /**
     * Copies the elements that are greater then element used for comparison
     * from one collection to another and returns the resultive collection.
     * Is designed for use with Fruits.
     * @param collection elements to compare
     * @param forComparison elements to compare with
     * @param <T> some type from fruits hierarchy
     * @return the collection of elements that are greater then element used for comparison
     */
    public static <T extends Fruit & Comparable<T>> Collection<T> getGreaterThen(
            Collection<T> collection, T forComparison) {

        Collection<T> result = new ArrayList<>();

        for (T obj : collection) {
            if (forComparison.compareTo(obj) < 0) {
                result.add(obj);
            }
        }

        return result;
    }

    /**
     * Entry point. Is used only for testing.
     * @param args
     */
    public static void main(String[]args){

        List<Fruit> fruits = null;
        List<Apple> apples = null;
        List<Orange> oranges = null;
        List<RedApple> redApples = null;

        copyAll(oranges, fruits);
        copyAll(redApples, fruits);
        copyAll(redApples, apples);
        copyAll(redApples, redApples);
    }

}

/**
 *
 */
class Apple extends Fruit implements Comparable<Apple> {
    Apple(int someId) {
        super(someId);
    }

    @Override
    public int compareTo(Apple o) {

        return someId - o.someId;
    }

    @Override
    public boolean equals(Object o) {

        if (this == o) {
            return true;
        }
        if (!(o instanceof Apple)) {
            return false;
        }

        Apple apple = (Apple) o;

        if (someId != apple.someId) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {

        return someId;
    }
}

/**
 *
 */
class RedApple extends Apple {
    RedApple(int someId) {
        super(someId);
    }
}

/**
 *
 */
class Orange extends Fruit {
    Orange(int someId) {
        super(someId);
    }
}

/**
 *
 */
class Melon {
}

